<script setup lang="ts">
import { ref, shallowRef, useTemplateRef } from 'vue'
import { gsap } from 'gsap'
import { ScrollTrigger } from 'gsap/ScrollTrigger'
import { getImgSrc } from '@/views/product/reno14-pro/image/4/img-src'
import { useEventListener, useThrottleFn } from '@vueuse/core'
import { useGsapContext } from '@/hooks'
import { useScrollGroup } from '@/hooks/reno14-pro.ts'

const { scrollGroup } = useScrollGroup()

const containerRef = useTemplateRef<HTMLDivElement | null>('containerRef')
const gridRef = useTemplateRef<HTMLDivElement | null>('gridRef')
interface Item {
  element: HTMLDivElement | null
  position: number
}

const itemRefs = ref<Item[]>([])
let median: number
const SCALE = 0.87

useGsapContext(() => {
  if (!containerRef.value || !gridRef.value) {
    return
  }

  const items = gridRef.value.querySelectorAll(
    '& > div div[data-item]',
  ) as NodeListOf<HTMLDivElement>
  const _itemsArr: Item[] = []
  items.forEach((i) => {
    _itemsArr.push({
      element: i,
      position: Number(i.dataset.item),
    })
  })
  itemRefs.value = _itemsArr

  const itemKeys = Object.keys(itemRefs.value)
  const medianIndex = (itemKeys.length - 1) / 2
  median = itemRefs.value[medianIndex].position

  itemRefs.value.forEach(({ element, position }) => {
    if (!element) {
      return
    }

    const contentEl = element.querySelector('& > div') as HTMLDivElement | null
    if (contentEl) {
      if (position !== median) {
        gsap.set(contentEl, { scale: SCALE })
      }
    }
  })

  const gridFirstItem = gridRef.value.querySelector('& > div:first-child') as HTMLDivElement | null
  const gridLastItem = gridRef.value.querySelector('& > div:last-child') as HTMLDivElement | null
  if (!gridFirstItem || !gridLastItem) {
    return
  }
  useEventListener(gridFirstItem, 'click', () => {
    move(false)
  })
  useEventListener(gridLastItem, 'click', () => {
    move(true)
  })

  ScrollTrigger.create({
    trigger: containerRef.value,
    start: 'top bottom',
    end: 'bottom top',
    onToggle: async (self) => {
      const video = getCenterVideo()

      if (self.isActive) {
        if (video) {
          centerVideo.value = video
          await video.play().catch()
        }
      } else {
        centerVideo.value = null
        if (video) {
          video.pause()
          video.currentTime = 0
        }
      }
    },
    invalidateOnRefresh: true,
    ...scrollGroup,
  })
})

const mod = (a: number, n: number): number => ((a % n) + n) % n
const getCenterVideo = () => {
  const centerItem = itemRefs.value.find((item) => item.position === median)
  const centerEl = centerItem?.element
  let video: HTMLVideoElement | null = null
  if (centerEl) {
    video = centerEl.querySelector('video') as HTMLVideoElement | null
  }
  return video
}

const centerVideo = shallowRef<HTMLVideoElement | null>(null)
useEventListener(centerVideo, 'ended', () => {
  setTimeout(async () => {
    await move(true)
  }, 300)
})

const currentPage = ref(0)
const move = useThrottleFn(async (next: boolean) => {
  itemRefs.value.forEach((item, index) => {
    const { element, position } = item
    if (!element) {
      return
    }
    const targetIndex = next ? mod(position + 1, 3) : mod(position - 1, 3)
    item.position = targetIndex

    const targetXPercent = (targetIndex - index) * 100
    const scale = targetIndex !== median ? SCALE : 0.999
    const zIndex = next ? 5 + targetIndex : 5 - targetIndex
    const duration = 1
    const ease = 'power3.inOut'

    gsap.set(element, { zIndex })
    gsap.to(element, { xPercent: targetXPercent, duration, ease })
    const contentEl = element.querySelector('& > div') as HTMLDivElement | null
    if (contentEl) {
      gsap.to(contentEl, { scale, duration, ease })
    }
  })

  currentPage.value = next ? mod(currentPage.value + 1, 3) : mod(currentPage.value - 1, 3)

  const video = getCenterVideo()
  if (video) {
    centerVideo.value = video
    await video.play().catch()
  }
}, 1000)

const videoData = [
  getImgSrc('videos-live-3-0_532.mp4'),
  getImgSrc('videos-live-3-1_532.mp4'),
  getImgSrc('videos-live-3-2_532.mp4'),
]
</script>

<template>
  <div
    ref="containerRef"
    class="mt-[0.375rem] bg-[#201f1c] rounded-sm py-[6.56vw] md:p-[1.5rem] lg:flex lg:px-[clamp(1.375rem,0.125rem+1.9531vw,2rem)] lg:py-[clamp(2rem,0rem+3.125vw,3rem)] lg:gap-x-[3rem]"
  >
    <div class="max-md:px-[5.6vw] lg:flex-1 lg:grid lg:content-center">
      <div class="text-3xl leading-[1.26] lg:text-[clamp(2rem,0rem+3.125vw,3rem)]">
        <p>实况照片动态壁纸</p>
        <p>念念不忘有回响</p>
      </div>

      <p
        class="mt-[1.375rem] text-base md:mt-[1rem] lg:text-[clamp(0.75rem,0rem+1.1719vw,1.125rem)]"
      >
        可爱萌宠的动态瞬间，旅拍风景的张力时刻，都能设为动态壁纸，每次亮屏重温拍摄时的情感和氛围。
      </p>
    </div>

    <div class="lg:flex-none lg:w-[64%]">
      <div
        class="w-full aspect-[96/91] my-[1.75rem] md:w-[68.75vw] md:mx-auto md:my-[1.5rem] md:aspect-[176/123] lg:w-full lg:aspect-[201/140] lg:mt-0"
      >
        <div
          ref="gridRef"
          class="w-full h-full grid grid-cols-[repeat(3,41.62vw)] grid-rows-1 justify-center overflow-hidden md:grid-cols-3"
        >
          <div v-for="(src, key) in videoData" :key class="w-full h-full relative">
            <div :data-item="key" class="w-full h-full relative pointer-events-none">
              <div class="w-full h-full grid place-items-center relative">
                <picture class="relative z-1">
                  <source
                    media="(min-width: 1024px)"
                    srcset="@/views/product/reno14-pro/image/4/images-live-3-frame-1.png.webp"
                  />
                  <source
                    media="(min-width: 640px)"
                    srcset="@/views/product/reno14-pro/image/4/images-live-3-frame-pad-1.png.webp"
                  />
                  <img
                    class="w-[97%] lg:w-[99%] mx-auto"
                    src="@/views/product/reno14-pro/image/4/images-live-3-frame-mo-1.png.webp"
                    alt=""
                    loading="lazy"
                  />
                </picture>

                <video
                  class="w-[91%] h-auto object-cover -translate-y-px rounded-2xl absolute inset-0 m-auto md:w-[91%] lg:w-[93%]"
                  muted
                  :src
                ></video>
              </div>
            </div>
          </div>
        </div>
      </div>

      <div class="flex justify-center items-center gap-[1.125rem]">
        <svg
          @click="move(false)"
          class="rotate-z-180 aspect-square w-[2.375rem] opacity-80 cursor-pointer lg:w-[clamp(2rem,0.75rem+1.9531vw,2.625rem)]"
        >
          <use href="#arrow-right-circle-white" />
        </svg>
        <div class="text-lg flex justify-center items-center">
          <p class="min-w-[0.75rem]">{{ currentPage + 1 }}</p>
          <p>/{{ itemRefs.length }}</p>
        </div>
        <svg
          @click="move(true)"
          class="aspect-square w-[2.375rem] opacity-80 cursor-pointer lg:w-[clamp(2rem,0.75rem+1.9531vw,2.625rem)]"
        >
          <use href="#arrow-right-circle-white" />
        </svg>
      </div>
    </div>
  </div>
</template>
